<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>2048</title>
    <link rel="stylesheet" href="./css/2048.css">
    <script src="./js/jquery-2.1.1.min.js"></script>
    <script src="./js/jquery.cookie.js"></script>
</head>

<body>
    <p id="score"></p>
    <div id="container">
        <a href="#" id="start">welcome to 2048!</a>
    </div>
</body>
<script>
    var start = document.getElementById('start');
    var container = document.getElementById('container')
    start.onclick = function () {
        this.style = "display:none";
    }


    function Game2048(container) {
        this.container = container;
        this.tiles = new Array(16);
        this.len = this.tiles.length;
    }

    Game2048.prototype = {
        init: function () {
            for (var i = 0; i < this.len; i++) {
                var tile = this.newTile('');
                this.container.appendChild(tile);
                this.tiles[i] = tile;
            }
            this.getRandom();
            this.getRandom();
        },
        newTile: function (value) {
            var tile = document.createElement('div');
            this.setValue(tile, value);
            return tile;
        },
        setValue: function (tile, value) {
            tile.className = "tile tile" + value;
            tile.setAttribute('val', value);
            tile.innerHTML = value > 0 ? value : '';
        },
        getRandom: function () {
            var zeroTile = [];
            // sTiles = Array.from(sTiles);
            // var zeroTile = sTiles.filter(function(item){
            //    return (item.getAttribute('val') == 0);
            // })
            //getElementsByName()与getElementsByTagName()方法的共同之类
            //是它们会把所取得的页面元素组成一个元素集合并非是数组,使用Array.form可以转换成数组
            for (var i = 0; i < this.len; i++) {
                if (this.tiles[i].getAttribute('val') == 0) {
                    zeroTile.push(this.tiles[i]);
                }
            }
            //将val为0的项放到数组里面去，根据数组的长度去随机值，就可以有效的避免已经赋值了的那一项
            var rNum = Math.floor(Math.random() * zeroTile.length);
            var initialValue = Math.random() > 0.7 ? 2 : 4;
            if(zeroTile.length>0)
                this.setValue(zeroTile[rNum], initialValue);//只有数组的长度大于一才能继续刷新出新的值出来
        },
        move: function (direction) {
            var j;
            switch (direction) {
                case "W":
                    for (var i = 0;i < this.len; i++) {
                        j = i;
                        while (j >= 4) {//向上排除第一行，所以j要大于4
                            this.merge(this.tiles[j - 4], this.tiles[j]);
                            j -= 4;
                        }
                    }
                    break;
                case "S":
                    for (var i = 0;i < this.len; i++) {
                        j = i;
                        while (j<12) {//向下要排除最后一行12-15，所以j要小于12
                            this.merge(this.tiles[j + 4], this.tiles[j]);
                            j += 4;
                        }
                    }
                    break;
                case "A":
                    for (var i = 0;i < this.len; i++) {
                        j = i;
                        while (j%4 != 0) {//向左要排除第一列，所以j%4 == 0 只有0,4,8，12，排除掉
                            this.merge(this.tiles[j - 1], this.tiles[j]);
                            j -= 1;
                        }
                    }
                    break;
                case "D":
                    for (var i = 0;i < this.len; i++) {
                        j = i;
                        while (j%4 != 3) {//向右要排除第三列，所以j%4 != 3,不能是最后一列
                            this.merge(this.tiles[j + 1], this.tiles[j]);
                            j += 1;
                        }
                    }
                    break;
                default : console.log('ERROR');
            }
            this.getRandom();//每次移动后刷新出一个新的块
        },
        merge: function (preTile, currTile) {// 合并，找到同一行或者同一列的两个元素，进行合并
            var preVal = preTile.getAttribute('val');
            var currVal = currTile.getAttribute('val');//获取他们的value值
            if(currVal != 0){//只有当前元素中有值的时候才能进行运算，否则就不予考虑
                if (preVal == 0) {
                    this.setValue(preTile,currVal);//显示preTile,将currVal的值赋给他，并设置好样式和类名
                    this.setValue(currTile,0);//隐藏自身
                } else if (preVal == currVal) {//如果两者相等的话*2
                    this.setValue(preTile,preVal*2);
                    this.setValue(currTile,0);
                }
            }
        },    
        over: function(){
            for(var i=0;i<this.len;i++){
                if(this.tiles[i].getAttribute('val') == 0){
                    return false;
                }
                if(i%4!=3){
                    if(this.tiles[i].getAttribute('val') == this.tiles[i+1].getAttribute('val')) 
                        return false;
                }
                if(i<12){
                    if(this.tiles[i].getAttribute('val') == this.tiles[i+4].getAttribute('val')) 
                        return false;
                }
            }
            return true;
        },
        success: function () {
            for(var i=0;i<this.len;i++){
                if(this.tiles[i].getAttribute('val') == 2048){
                    alert('success!');
                }
            }
        },
        score: function () {
            var totalScore = 0;
            for(var i =0; i<this.len;i++){
                totalScore =totalScore + parseInt(this.tiles[i].getAttribute('val'),10); 
            }
            alert('Game over!Your score is '+ totalScore);
            return totalScore;
        },
        restart: function(){
            var that = this;
            start.style="display:block";
            start.innerHTML="Do you want to replay ?";
            start.onclick = function(){
                start.style="display:none";
                that.clear();
                that.init();
            }
        },
        clear:function(){
            for(var i=0;i<this.len;i++){
                this.container.removeChild(this.tiles[i]);
            }
        }
    }

    window.onkeydown = function(e){//onkeydown 键盘按下绑定事件
        var keynum, keychar;
        if(window.event){//IE下获取键盘按下的值
            keynum = e.keyCode;
        }
        else if(e.which){//其他浏览器按下获取的值
            keynum = e.which;
        }
        keychar = String.fromCharCode(keynum);//将键盘按下获取到的数值转换成字符
        if(['W','S','A','D'].indexOf(keychar) != -1){//判断按下的字符是否在 W,A,S,D中，如果在，就执行move
            if(Game.over()){
                var currentScore=Game.score();//只能执行一次，否则最后结束时只要按键按下就会一直显示分数
                if(currentScore>$.cookie('HScore')){
                    $.cookie('HScore',currentScore);
                    document.getElementById('score').innerText="最高的得分为："+$.cookie('HScore');
                }
                Game.restart();
            }
            Game.success();
            Game.move(keychar);
        }
    }
    console.log($.cookie('HScore'));
    if($.cookie('HScore')==null){
        $.cookie('HScore', 0, { path: '/', expires: 10 });
    }
    document.getElementById('score').innerText="最高的得分为："+$.cookie('HScore');
    var Game = new Game2048(container);
    Game.init();

</script>

</html>